
#include "drv_db_column.h"
#include "drv_db_table.h"

/***************************************************************
* Name:   db_type_to_str()
* Input : type 数据类型
* Output: void 
* Return: !=NULL 数据类型对应的字符串 NULL 异常类型
* Author: heweilong
* Revise: V1.0
* Description: 数据类型对应的字符串
***************************************************************/
static const char* db_type_to_str(uint8_t type)
{
	switch(type) {
			case SQLITE_INTEGER:
			{
				return "INTEGER";
			}
			case SQLITE_FLOAT:
			{
				return "REAL";
			}
			case SQLITE_TEXT:
			{
				return "TEXT";
			}
			case SQLITE_BLOB:
			{
				return "BLOB";
			}
			default:
			{
				DB_DB_LOG_ERROR("NO DEF TYPE");
				return NULL;
			}
	}
}

/***************************************************************
* Name:   db_type_to_str()
* Input : str 数据类型字符串
* Output: void 
* Return: 数据类型 -1 异常字符串
* Author: heweilong
* Revise: V1.0
* Description: 字符串对应的数据类型
***************************************************************/
static const uint8_t db_str_to_type(char* str)
{
	if(strcmp(str, "INTEGER") == 0)
	{
		return SQLITE_INTEGER;
	}
	else if(strcmp(str, "REAL") == 0)
	{
		return SQLITE_FLOAT;
	}
	else if(strcmp(str, "TEXT") == 0)
	{
		return SQLITE_TEXT;
	}
	else if(strcmp(str, "BLOB") == 0)
	{
		return SQLITE_BLOB;
	}
	else
	{
		return -1;
	}
}


/***************************************************************
* Name:   db_cons_to_str()
* Input : buf 存储转换为字符串的空间 buf_size 空间大小 constraint 限制条件
* Output: void 
* Return: 1 有变动 0 没变动 -1 异常
* Author: heweilong
* Revise: V1.0
* Description: 限制条件转为字符串
***************************************************************/
static int db_cons_to_str(char* buf, size_t buf_size, const db_field_feature_t constraint)
{
	if(buf == NULL || buf_size == 0)
	{
		return -1;
	}

	memset(buf, 0x00, buf_size);

	if(constraint == FEAT_NONE)
	{
		return 0;
	}
	
	if((constraint & FEAT_NOT_NULL) == FEAT_NOT_NULL)	//不能为空
	{
		if(snprintf(NULL, 0, "%s NOT NULL", buf) + 1 <= buf_size)
		{
			strcat(buf, " NOT NULL");
		}
		else
		{
			return -1;
		}
	}

	if((constraint & FEAT_UNIQUE) == FEAT_UNIQUE)	//唯一值 
	{
		if(snprintf(NULL, 0, "%s UNIQUE", buf) + 1 <= buf_size)
		{
			strcat(buf, " UNIQUE");
		}
		else
		{
			return -1;
		}
	}

	if((constraint & FEAT_PRIMARY_KEY) == FEAT_PRIMARY_KEY)	//主键
	{
		if(snprintf(NULL, 0, "%s PRIMARY KEY", buf) + 1 <= buf_size)
		{
			strcat(buf, " PRIMARY KEY");
		}
		else
		{
			return -1;
		}
	}
	
	if((constraint & FEAT_AUTOINC) == FEAT_AUTOINC)	//自动
	{
		if(snprintf(NULL, 0, "%s AUTOINCREMENT", buf) + 1 <= buf_size)
		{
			strcat(buf, " AUTOINCREMENT");
		}
		else
		{
			return -1;
		}
	}

	return 1;
}

/***************************************************************
* Name:   create_table()
* Input : db 数据库 table_name 创建表的表名 data 创建表的参数
* Output: void 
* Return: SQLITE_OK 创建成功
* Author: heweilong
* Revise: V1.0
* Description: 创建表
***************************************************************/
static int create_table(sqlite3* db, const char* table_name, const void* data)
{
	const db_create_table_params_t* params = (const db_create_table_params_t*) data;

	// 构建CREATE TABLE语句
	char sql[1024] = {0};
	snprintf(sql, sizeof(sql), "CREATE TABLE IF NOT EXISTS %s (", table_name);

	// 拼接列定义
	for (size_t i = 0; i < params->col_count; i++)
	{
		db_column_definition_t* col = &params->col_def[i];

		strcat(sql, col->col_type.column_name);
		strcat(sql, " ");

		/*判断类型是否正常*/
		if(db_type_to_str(col->col_type.data_type) != NULL)
		{
			strcat(sql, db_type_to_str(col->col_type.data_type));
		}
		else
		{
			return SQLITE_ERROR;
		}

		char cons_str[64] = "";
		int rc = db_cons_to_str(cons_str, sizeof(cons_str), col->cons);
		if (rc == 1)
		{
			strcat(sql, cons_str);
		}
		else if(rc == -1)
		{
			return SQLITE_ERROR;
		}

		char* default_data;
		/*默认值*/
		switch (col->col_type.data_type)
		{
			case SQLITE_INTEGER:
			{
				int sql_len = snprintf(NULL, 0, " DEFAULT %d", col->col_type.value.int_value) + 1;
				default_data = malloc(sql_len);
				if(default_data == NULL)
				{
					DB_DB_LOG_ERROR("malloc fail");
					return SQLITE_ERROR;
				}
				snprintf(default_data, sql_len, " DEFAULT %d", col->col_type.value.int_value);
				break;
			}
			case SQLITE_FLOAT:
			{
				int sql_len = snprintf(NULL, 0, " DEFAULT %.2f", col->col_type.value.float_value) + 1;
				default_data = malloc(sql_len);
				if(default_data == NULL)
				{
					DB_DB_LOG_ERROR("malloc fail");
					return SQLITE_ERROR;
				}
				snprintf(default_data, sql_len, " DEFAULT %.2f", col->col_type.value.float_value);
				break;
			}
			case SQLITE_NULL:
			{
				break;
			}
			case SQLITE_TEXT:
			{
				int sql_len = snprintf(NULL, 0, " DEFAULT %s", col->col_type.value.text_value) + 1;
				default_data = malloc(sql_len);
				if(default_data == NULL)
				{
					DB_DB_LOG_ERROR("malloc fail");
					return SQLITE_ERROR;
				}
				snprintf(default_data, sql_len, " DEFAULT %s", col->col_type.value.text_value);
				break;
			}
			default:
			{
				DB_DB_LOG_ERROR("NO DEF TYPE :%d", col->col_type.data_type);
				return SQLITE_ERROR;
			}
		}
		strcat(sql, default_data);
		free(default_data);

		if (i != params->col_count - 1)
		{
			strcat(sql, ", ");
		}
	}
	strcat(sql, ");");

	/*执行语句*/
	return sqlite3_exec(db, sql, 0, 0, NULL);
}

/***************************************************************
* Name:   delete_table()
* Input : db 数据库 table_name 删除表的表名 data 没用
* Output: void 
* Return: SQLITE_OK 创建成功
* Author: heweilong
* Revise: V1.0
* Description: 删除表
***************************************************************/
static int delete_table(sqlite3* db, const char* table_name, const void* data)
{
	char sql[256];
	snprintf(sql, sizeof(sql), "DROP TABLE IF EXISTS %s", table_name);

	/*执行语句*/
	return sqlite3_exec(db, sql, 0, 0, NULL);
}

/***************************************************************
* Name:   get_info()
* Input : db 数据库 table_name 查询表的表名 data 没用
* Output: void 
* Return: 查询到的信息
* Author: heweilong
* Revise: V1.0
* Description: 查询表
***************************************************************/
static db_create_table_params_t* get_info(sqlite3* db, const char* table_name, const void* data)
{
	// 使用PRAGMA获取表信息
	char sql[256];
	snprintf(sql, sizeof(sql), "PRAGMA table_info(%s)", table_name);

	sqlite3_stmt* stmt = NULL;
	if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
	{
		DB_ERROR(db);
		return NULL;
	}

	db_create_table_params_t* table_info = calloc(1, sizeof(db_create_table_params_t));

	// 临时存储列信息的数组
	int capacity = 10;	//数据项
	int count = 0;
	db_column_definition_t* columns = malloc(sizeof(db_column_definition_t) * capacity);
	if(columns == NULL)
	{
		DB_SAFE_FINALIZE(stmt);
		DB_ERROR(db);
		return NULL;
	}

	while (sqlite3_step(stmt) == SQLITE_ROW)
	{
		/*初始空间不够 申请空间*/
		if (count >= capacity)
		{
			capacity *= 2;
			columns = realloc(columns, sizeof(db_column_definition_t) * capacity);
		}

		// 解析PRAGMA结果
		columns[count].col_type.column_name = strdup((const char*)sqlite3_column_text(stmt, 1));
		columns[count].col_type.data_type = db_str_to_type(strdup((const char*)sqlite3_column_text(stmt, 2)));
		
		// 解析约束
		columns[count].cons = 0;
		if (sqlite3_column_int(stmt, 3) > 0)
		{
			columns[count].cons |= FEAT_NOT_NULL;
		}
		if (sqlite3_column_int(stmt, 5) > 0)
		{
			columns[count].cons |= FEAT_PRIMARY_KEY;
		}

		count++;
	}

	/*保存数据*/
	table_info->col_def = realloc(columns, sizeof(db_column_definition_t) * count);
	table_info->col_count = count;

	DB_SAFE_FINALIZE(stmt);
	return table_info;
}

/***************************************************************
* Name:   drv_db_create_table()
* Input : db 数据库 table_name 创建的表名 params 创建时的参数
* Output: void 
* Return: SQLITE_OK 合格
* Author: heweilong
* Revise: V1.2
* Description: 创建表
***************************************************************/
int drv_db_create_table(sqlite3* db, const char* table_name, const db_create_table_params_t* params)
{
	/* 参数校验 */
	if(db == NULL)
	{
		DB_DB_LOG_ERROR("db = null\n");
		return SQLITE_ERROR;
	}
	else if(table_name == NULL)
	{
		DB_DB_LOG_ERROR("table_name = null\n");
		return SQLITE_ERROR;
	}
	else if (!db_is_valid_identifier(table_name))	//验证表名和列名 是否规范
	{
		DB_DB_LOG_ERROR("Invalid table name: %s\n", table_name);
		return SQLITE_ERROR;
	}
	else if (params->col_def == NULL)
	{
		DB_DB_LOG_ERROR("param.param == NULL\n");
		return SQLITE_ERROR;
	}
	else if (params->col_count == 0)
	{
		DB_DB_LOG_ERROR("param.param_count = null\n");
		return SQLITE_ERROR;
	}
	else
	{
		for(int i = 0; i < params->col_count; i++)
		{
			db_column_value_t value = params->col_def[i].col_type;
			if (!value.column_name ||
					!db_is_valid_identifier(value.column_name ))
			{
				DB_DB_LOG_ERROR("param:%d Invalid column name: %s\n", i, value.column_name );
				return SQLITE_ERROR;
			}
		}
	}

	return db_transaction_wrapper(db, create_table, table_name, (void*)(params));
}

/***************************************************************
* Name:   drv_db_delete_table()
* Input : db 数据库 table_name 删除的表名
* Output: void 
* Return: SQLITE_OK 合格
* Author: heweilong
* Revise: V1.2
* Description: 删除表
***************************************************************/
int drv_db_delete_table(sqlite3* db, const char* table_name)
{
	/* 参数校验 */
	if(db == NULL)
	{
		DB_DB_LOG_ERROR("db = null\n");
		return SQLITE_ERROR;
	}
	else if(table_name == NULL)
	{
		DB_DB_LOG_ERROR("table_name = null\n");
		return SQLITE_ERROR;
	}
	else if (!db_is_valid_identifier(table_name))	//验证表名和列名 是否规范
	{
		DB_DB_LOG_ERROR("Invalid table name: %s\n", table_name);
		return SQLITE_ERROR;
	}

	return db_transaction_wrapper(db, delete_table, table_name, NULL);
}

/***************************************************************
* Name:   drv_db_find_table()
* Input : db 数据库 table_name 查找的表名
* Output: void 
* Return: !=NULL 表存在 =NULL 表不存在
* Author: heweilong
* Revise: V1.2
* Description: 查询表
***************************************************************/
db_create_table_params_t* drv_db_find_table(sqlite3* db, const char* table_name)
{
	/* 参数校验 */
	if(db == NULL)
	{
		DB_DB_LOG_ERROR("db = null\n");
		return NULL;
	}
	else if(table_name == NULL)
	{
		DB_DB_LOG_ERROR("table_name = null\n");
		return NULL;
	}
	else if (!db_is_valid_identifier(table_name))	//验证表名和列名 是否规范
	{
		DB_DB_LOG_ERROR("Invalid table name: %s\n", table_name);
		return NULL;
	}

	return get_info(db, table_name, NULL);
}

/***************************************************************
* Name:   drv_db_printf_table_info()
* Input : table_info 存储空间
* Output: void 
* Return: void
* Author: heweilong
* Revise: V1.0
* Description: 打印存储的信息数据
***************************************************************/
void drv_db_printf_table_info(const db_create_table_params_t* table_info)
{
	for (size_t i = 0; i < table_info->col_count; i++)
	{
		char buf[50];
		db_cons_to_str(buf, sizeof(buf), table_info->col_def[i].cons);
		DB_LOG_INFO("NAME:%s TYPE:%s CONS:%s", 
			table_info->col_def[i].col_type.column_name,
			db_type_to_str(table_info->col_def[i].col_type.data_type),
			buf);
	}
	
}

/***************************************************************
* Name:   drv_db_free_table_info()
* Input : table_info 存储空间
* Output: void 
* Return: void
* Author: heweilong
* Revise: V1.0
* Description: 释放存储的信息数据内存
***************************************************************/
void drv_db_free_table_info(db_create_table_params_t* table_info)
{
	if (!table_info)
		return;

	for (int i = 0; i < table_info->col_count; i++)
	{
		db_column_definition_t* col = &table_info->col_def[i];

		if (col->col_type.column_name)
		{
			free(col->col_type.column_name);
		}
	}

	if(table_info->col_def != NULL)
	{
		free(table_info->col_def);
	}
	free(table_info);
}
